using System;
using System.Drawing;
using System.Windows.Forms;
using RideMe.AddIns.Events;
using RideMe.AddIns.Interfaces;

namespace RideMe.AddIns.Logging.Project
{
    /// <summary>
    /// This add-in simply keeps a log of project events, such as files being added, removed etc, using the project service
    /// </summary>
    public class ProjectEventsLoggerAddIn : IAddIn
    {
        #region Private Variables

        //We keep a delegate to these two methods hanging around as we need them outside of the event handler
        private AddControlHandler AddControl = null;
        private RemoveControlHandler RemoveControl = null;

        //Controls used to render the various aspects of the add-in
        private ToolStripMenuItem toggleProjectLoggingMenuItem;
        private TextBox eventLogTextBox;
        private CheckBox eventLogEnabledCheckBox;
        private CheckBox eventLogVisibleCheckBox;

        //Used to keep a record of whether the add-in is activated or not
        private static bool _enabled = true;

        #endregion

        #region Methods

        /// <summary>
        /// This hides the control using the remove control delegate
        /// </summary>
        private void HideControl()
        {
            if (RemoveControl != null)
                RemoveControl(eventLogTextBox);
        }

        /// <summary>
        /// This shows the control using the add control delegate
        /// </summary>
        private void ShowControl()
        {
            if (AddControl != null)
                AddControl(eventLogTextBox);
        }

        /// <summary>
        /// This creates the text log control
        /// </summary>
        /// <param name="name"></param>
        private void CreateTextBox(string name)
        {
            //Create our text box, ensure user input isn't allowed, and then also ensure it can display multiple lines of text
            eventLogTextBox = new TextBox();
            eventLogTextBox.Name = name;
            eventLogTextBox.Enabled = false;
            eventLogTextBox.Multiline = true;
            eventLogTextBox.BackColor = Color.White;
        }

        /// <summary>
        /// This creates the options enabled check box
        /// </summary>
        private void CreateEnabledCheckBox()
        {
            //Create our option checkbox
            eventLogEnabledCheckBox = new CheckBox();
            eventLogEnabledCheckBox.Checked = _enabled;
            eventLogEnabledCheckBox.Location = new Point(20, 20);
            eventLogEnabledCheckBox.Enabled = true;
            eventLogEnabledCheckBox.Text = "Enable?";
            eventLogEnabledCheckBox.CheckedChanged += new EventHandler(eventLogEnabledCheckBox_CheckedChanged);
        }

        /// <summary>
        /// This creates the options visible check box
        /// </summary>
        private void CreateVisibleCheckBox()
        {
            //Create our option checkbox
            eventLogVisibleCheckBox = new CheckBox();
            eventLogVisibleCheckBox.Checked = eventLogTextBox.Parent.Parent != null;
            eventLogVisibleCheckBox.Location = new Point(20, 40);
            eventLogVisibleCheckBox.Enabled = true;
            eventLogVisibleCheckBox.Text = "Visible?";
            eventLogVisibleCheckBox.CheckedChanged += new EventHandler(eventLogVisibleCheckBox_CheckedChanged);
        }
        
        /// <summary>
        /// This helper method logs the specified message to the text box control
        /// </summary>
        /// <param name="message"></param>
        private void LogLine(string message)
        {
            if (eventLogTextBox.InvokeRequired)
            {
                eventLogTextBox.Invoke(
                    new MethodInvoker(
                    delegate
                    {
                        LogLine(message);
                    }));
            }
            else
            {

                //If the logger is disabled, then we want to stop logging
                if (eventLogEnabledCheckBox != null && !eventLogEnabledCheckBox.Checked)
                    return;
                //Log to the text box
                eventLogTextBox.Text += string.Format("{0}{1}", message, Environment.NewLine);
            }
        }

        #endregion

        #region Delegates

        //Delegates to capture references to the add and remove control methods for use outside the control created event handler
        public delegate void AddControlHandler(Control control);
        public delegate void RemoveControlHandler(Control control);

        #endregion

        #region Events

        /// <summary>
        /// This ensures that the enabled flag is set accordingly
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void eventLogEnabledCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            _enabled = eventLogEnabledCheckBox.Checked;
        }

        /// <summary>
        /// This shows or hides the control dependent on setting
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void eventLogVisibleCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            if (eventLogVisibleCheckBox.Checked)
                ShowControl();
            else
                HideControl();
        }

        /// <summary>
        /// This responds to a project being opened
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProjectEvents_ProjectOpened(object sender, ProjectEventSource.FileEventArgs e)
        {
            LogLine(string.Format("{0}: project opened", e.Path));
        }

        /// <summary>
        /// This responds to a project being created
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProjectEvents_ProjectCreated(object sender, ProjectEventSource.FileEventArgs e)
        {
            LogLine(string.Format("{0}: project created", e.Path));
        }

        /// <summary>
        /// This responds to a project being closed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProjectEvents_ProjectClosed(object sender, ProjectEventSource.FileEventArgs e)
        {
            LogLine(string.Format("{0}: project closed", e.Path));
        }

        /// <summary>
        /// This responds to a file being opened
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProjectEvents_FileOpened(object sender, ProjectEventSource.FileEventArgs e)
        {
            LogLine(string.Format("{0}: file opened", e.Path));
        }

        /// <summary>
        /// This responds to a file being selected
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProjectEvents_FileSelected(object sender, ProjectEventSource.FileEventArgs e)
        {
            LogLine(string.Format("{0}: file selected", e.Path));
        }

        /// <summary>
        /// This responds to a file being renamed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProjectEvents_FileRenamed(object sender, ProjectEventSource.RenamedFileEventArgs e)
        {
            LogLine(string.Format("{0}: file renamed to {1}", e.OldPath, e.NewPath));
        }

        /// <summary>
        /// This responds to a file being deleted
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProjectEvents_FileDeleted(object sender, ProjectEventSource.FileEventArgs e)
        {
            LogLine(string.Format("{0}: file deleted", e.Path));
        }

        /// <summary>
        /// This responds to a file being closed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProjectEvents_FileClosed(object sender, ProjectEventSource.FileEventArgs e)
        {
            LogLine(string.Format("{0}: file closed", e.Path));
        }

        /// <summary>
        /// This sets up the various option controls needed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void UserInterfaceEvents_OptionsControlCreated(object sender, RideMe.AddIns.Events.UserInterfaceEventSource.ControlCreatedEventArgs e)
        {
            CreateEnabledCheckBox();
            e.AddControl(eventLogEnabledCheckBox);
            CreateVisibleCheckBox();
            e.AddControl(eventLogVisibleCheckBox);
        }

        /// <summary>
        /// This places the main logger control in the left dock control, and also captures delegates so that it's trivial to add/remove controls from other methods
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void UserInterfaceEvents_LeftDockControlCreated(object sender, RideMe.AddIns.Events.UserInterfaceEventSource.DockControlCreatedEventArgs e)
        {
            e.AddControl(eventLogTextBox);
            AddControl = new AddControlHandler(e.AddControl);
            RemoveControl = new RemoveControlHandler(e.RemoveControl);
        }

        /// <summary>
        /// This creates the menu for the logger
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void UserInterfaceEvents_MenuCreated(object sender, RideMe.AddIns.Events.UserInterfaceEventSource.MenuCreatedEventArgs e)
        {
            ToolStripMenuItem loggingMenuItem = new ToolStripMenuItem("Logging");
            loggingMenuItem.Click += new EventHandler(loggingMenuItem_Click);
            toggleProjectLoggingMenuItem = new ToolStripMenuItem("Hide Project Logging");
            toggleProjectLoggingMenuItem.Click += new EventHandler(toggleProjectLoggingMenuItem_Click);
            loggingMenuItem.DropDownItems.Add(toggleProjectLoggingMenuItem);
            e.AddMenuItem(loggingMenuItem);
        }

        /// <summary>
        /// This ensures the text of the menu item to show/hide the project logging is correct
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void loggingMenuItem_Click(object sender, EventArgs e)
        {
            if (eventLogTextBox.Parent.Parent != null)
                toggleProjectLoggingMenuItem.Text = "Hide Project Logging";
            else
                toggleProjectLoggingMenuItem.Text = "Show Project Logging";
        }

        /// <summary>
        /// This shows/hides the logging control
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void toggleProjectLoggingMenuItem_Click(object sender, EventArgs e)
        {
            switch (eventLogTextBox.Parent.Parent != null)
            {
                case true:
                    HideControl();
                    break;
                case false:
                    ShowControl();
                    break;
            }
        }

        #endregion

        #region IAddIn Members

        /// <summary>
        /// This returns the name of the add-in
        /// </summary>
        public string Name
        {
            get { return "Project Events Logger Add-In"; }
        }

        /// <summary>
        /// This returns the author of the add-in
        /// </summary>
        public string Author
        {
            get { return "El Draper <el@eldiablo.co.uk>"; }
        }

        /// <summary>
        /// This returns the description of the add-in
        /// </summary>
        public string Description
        {
            get { return "Keeps a simple text log of project events as they happen"; }
        }

        /// <summary>
        /// This initialises the control, and connects to the required events
        /// </summary>
        /// <param name="context"></param>
        public void Init(IApplicationContext context)
        {
            CreateTextBox(this.Name);
            //Connect to UI events
            context.UserInterfaceEvents.MenuCreated += new EventHandler<RideMe.AddIns.Events.UserInterfaceEventSource.MenuCreatedEventArgs>(UserInterfaceEvents_MenuCreated);
            context.UserInterfaceEvents.LeftDockControlCreated += new EventHandler<RideMe.AddIns.Events.UserInterfaceEventSource.DockControlCreatedEventArgs>(UserInterfaceEvents_LeftDockControlCreated);
            context.UserInterfaceEvents.OptionsControlCreated += new EventHandler<RideMe.AddIns.Events.UserInterfaceEventSource.ControlCreatedEventArgs>(UserInterfaceEvents_OptionsControlCreated);
            //Connect to project events
            context.ProjectEvents.FileClosed += new EventHandler<ProjectEventSource.FileEventArgs>(ProjectEvents_FileClosed);
            context.ProjectEvents.FileDeleted += new EventHandler<ProjectEventSource.FileEventArgs>(ProjectEvents_FileDeleted);
            context.ProjectEvents.FileOpened += new EventHandler<ProjectEventSource.FileEventArgs>(ProjectEvents_FileOpened);
            context.ProjectEvents.FileRenamed += new EventHandler<ProjectEventSource.RenamedFileEventArgs>(ProjectEvents_FileRenamed);
            context.ProjectEvents.FileSelected += new EventHandler<ProjectEventSource.FileEventArgs>(ProjectEvents_FileSelected);
            context.ProjectEvents.ProjectClosed += new EventHandler<ProjectEventSource.FileEventArgs>(ProjectEvents_ProjectClosed);
            context.ProjectEvents.ProjectCreated += new EventHandler<ProjectEventSource.FileEventArgs>(ProjectEvents_ProjectCreated);
            context.ProjectEvents.ProjectOpened += new EventHandler<ProjectEventSource.FileEventArgs>(ProjectEvents_ProjectOpened);
        }        

        /// <summary>
        /// This is called to free all resources with this add-in
        /// </summary>
        public void Destroy()
        {
            AddControl = null;
            RemoveControl = null;
        }

        #endregion
    }
}
